home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
ue312src.zip
/
MOUSE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-06
|
17KB
|
696 lines
/* MOUSE.C: Mouse functionality commands
for MicroEMACS 3.12
originally written by Dave G. Conroy
modified by Jeff Lomicka and Daniel Lawrence
*/
#include <stdio.h>
#include "estruct.h"
#include "eproto.h"
#include "edef.h"
#include "elang.h"
#define MNONE 0 /* Mouse commands. */
#define MMOVE 1
#define MREGDWN 2
#define MREGUP 3
#define MCREATE 4
#define MDELETE 5
#if MOUSE
NOSHARE int lastypos = HUGE; /* Last mouse event row. */
NOSHARE int lastxpos = HUGE; /* Last mouse event column. */
NOSHARE int lastmcmd = MNONE; /* Last mouse command. */
/*
* Move mouse button, down. The window that the
* mouse is in is always selected (this lets you select a
* window by clicking anyplace in it, even off the end
* of the text). If the mouse points at text then dot is
* moved to that location.
*/
PASCAL NEAR movemd(f, n)
int f,n; /* prefix flag and argument */
{
register WINDOW *wp;
register WINDOW *lastwp;
register LINE *lp;
/* make sure we are on the proper screen */
mouse_screen();
/* adjust position by screen offset */
ypos -= term.t_roworg;
xpos -= term.t_colorg;
/* if anything has changed, reset the click count */
if (lastmcmd != MMOVE || lastypos!=ypos || lastxpos!=xpos)
nclicks = 0;
++nclicks;
lastwp = mousewindow(lastypos); /* remember last window */
/* reset the last position */
lastypos = ypos;
lastxpos = xpos;
lastmcmd = MMOVE;
/* if we move the mouse off the windows, don't do anything with it */
if ((wp=mousewindow(ypos)) == NULL)
return(FALSE);
/* if we are on the line with the point, adjust for extended lines */
if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
xpos += lbound;
/* make the window the mouse points to current */
curwp = wp;
curbp = wp->w_bufp;
/* if we changed windows, update the modelines */
if (wp != lastwp)
upmode();
/* if we aren't off the end of the text, move the point to the mouse */
if ((lp=mouseline(wp, ypos)) != NULL) {
curwp->w_dotp = lp;
curwp->w_doto = mouseoffset(wp, lp, xpos);
}
return(TRUE);
}
/* mouse-move: adjust the hilited region by setting mark(hilite+1)
only if we are holding down the proper button
*/
PASCAL NEAR mmove(f, n)
int f,n; /* prefix flag and argument */
{
register WINDOW *wp;
register WINDOW *lastwp;
register LINE *lp;
register int lastmodeline; /* was the dowbclick on a modeline? */
register int lastcmdline; /* was the downclick on the command line? */
/* ignore this if not hilighting */
if (hilite >= NMARKS)
return(TRUE);
/* ignore this if we did not just do a mouse region down */
if (lastmcmd != MREGDWN)
return(TRUE);
/* adjust position by screen offset */
ypos -= term.t_roworg;
xpos -= term.t_colorg;
/* Just where was the last click? */
lastwp = mousewindow(lastypos);
lastmodeline = ismodeline(lastwp, lastypos);
lastcmdline = (lastypos == term.t_nrow);
/* if it was on a modeline or the command line, don't do things here */
if (lastmodeline || lastcmdline)
return(FALSE);
/* if we move the mouse off the window, abort this */
if ((wp = mousewindow(ypos)) == NULL || wp != lastwp)
return(FALSE);
/* if we are on the line with the point, adjust for extended lines */
if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
xpos += lbound;
/* if we aren't off the end of the text, set mark $hilight+1 */
if ((lp=mouseline(wp, ypos)) != NULL) {
wp->w_markp[hilite+1] = lp;
wp->w_marko[hilite+1] = mouseoffset(wp, lp, xpos);
}
return(TRUE);
}
/* mouse-region-down: mouse region operations
nclicks = 0: move cursor to mouse
if hiliting then
hilite set-mark
set-mark
1: move cursor to mouse
kill-region
*/
PASCAL NEAR mregdown(f, n)
int f,n; /* prefix flag and argument */
{
register WINDOW *wp;
register WINDOW *lastwp;
register LINE *lp;
SCREEN *sp;
char scr_name[12]; /* constructed temp screen name */
static int temp_count = 0; /* next temp screen number! */
/* make sure we are on the proper screen */
mouse_screen();
/* adjust position by screen offset */
ypos -= term.t_roworg;
xpos -= term.t_colorg;
/* if anything has changed, reset the click count */
if (((lastmcmd != MREGUP) && (lastmcmd != MREGDWN))
|| lastypos != ypos || lastxpos != xpos)
nclicks = 0;
++nclicks;
lastwp = mousewindow(lastypos); /* remember last window */
/* reset the last position */
lastypos = ypos;
lastxpos = xpos;
lastmcmd = MREGDWN;
#if !WINDOW_MSWIN
/* if we are in the upper left corner, create a new window */
if (xpos == 0 && ypos == 0) {
/* get the name of the screen to create */
strcpy(scr_name, "SCREEN");
strcat(scr_name, int_asc(temp_count++));
while (lookup_screen(scr_name) != (SCREEN *)NULL) {
strcpy(scr_name, "SCREEN");
strcat(scr_name, int_asc(temp_count++));
}
/* save the current dot position in the buffer info
so the new screen will start there! */
curbp->b_dotp = curwp->w_dotp;
curbp->b_doto = curwp->w_doto;
/* screen does not exist, create it */
sp = init_screen(scr_name, curbp);
/* and make this screen current */
return(select_screen(sp, TRUE));
}
#endif
/* if we move the mouse off the windows, don't move anything */
if ((wp=mousewindow(ypos)) == NULL)
return(FALSE);
/* if we are on the line with the point, adjust for extended lines */
if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
xpos += lbound;
/* make the window the mouse points to current */
curwp = wp;
curbp = wp->w_bufp;
/* if we changed windows, update the modelines */
if (wp != lastwp)
upmode();
/* if we aren't off the end of the text, move the point to the mouse */
if ((lp=mouseline(wp, ypos)) != NULL) {
curwp->w_dotp = lp;
curwp->w_doto = mouseoffset(wp, lp, xpos);
}
/* perform the region function */
if (nclicks == 1) {
if (hilite < NMARKS) {
curwp->w_markp[hilite+1] = NULL;
curwp->w_marko[hilite+1] = 0;
curwp->w_markp[hilite] = curwp->w_dotp;
curwp->w_marko[hilite] = curwp->w_doto;
}
return(setmark(FALSE, 0));
} else {
lastflag &= ~CFKILL;
return(killregion(FALSE, 0));
}
}
/* mouse-region-up: mouse region operations
If the corrosponding downclick was on a modeline, then we
wish to delete the indicated window. Otherwise we are using
this button to copy/paste.
nclicks = 0: move cursor to mouse
copy-region
1: move cursor to mouse
yank
3: reset nclicks to 0
*/
PASCAL NEAR mregup(f, n)
int f,n; /* prefix flag and argument */
{
register WINDOW *wp;
register WINDOW *lastwp;
register LINE *lp;
register SCREEN *sp; /* ptr to screen to delete */
register int lastmodeline; /* was the dowbclick on a modeline? */
register int lastcmdline; /* was the downclick on the command line? */
/* adjust position by screen offset */
ypos -= term.t_roworg;
xpos -= term.t_colorg;
/* if anything has changed, reset the click count */
if (((lastmcmd != MREGUP) && (lastmcmd != MREGDWN))
|| lastypos != ypos || lastxpos != xpos)
nclicks = 0;
++nclicks;
lastwp = mousewindow(lastypos); /* remember last window */
#if !WINDOW_MSWIN
/* if the down click was in the upper left corner...
then we are moving a just created screen */
if (lastypos == 0 && lastxpos == 0) {
new_row_org(TRUE, ypos + term.t_roworg);
new_col_org(TRUE, xpos + term.t_colorg);
#if WINDOW_TEXT
refresh_screen(first_screen);
#endif
return(TRUE);
}
#endif
/* Just where was the last click? */
lastmodeline = ismodeline(lastwp, lastypos);
lastcmdline = (lastypos == term.t_nrow);
/* reset the last position */
lastypos = ypos;
lastxpos = xpos;
lastmcmd = MREGUP;
/* if we started on a modeline.... */
if (lastmodeline)
return(delwind(TRUE, 0));
/* if we are on a command line */
if (lastcmdline) {
if (ypos != term.t_nrow)
/* ABORT ABORT ABORT screen deletion */
return(TRUE);
else {
/* delete the screen last screen means exiting */
if (first_screen->s_next_screen == (SCREEN *)NULL)
return(quit(FALSE, 0));
/* bring the second last screen to front*/
sp = first_screen;
select_screen(sp->s_next_screen, FALSE);
/* and dump the front screen */
first_screen->s_next_screen = sp->s_next_screen;
free_screen(sp);
#if WINDOW_TEXT
refresh_screen(first_screen);
#endif
return(TRUE);
}
}
/* if we move the mouse off the windows, don't move anything */
if ((wp=mousewindow(ypos)) == NULL)
return(FALSE);
/* if we are on the line with the point, adjust for extended lines */
if (wp == curwp && (lp = mouseline(wp, ypos)) == curwp->w_dotp)
xpos += lbound;
/* make the window the mouse points to current */
curwp = wp;
curbp = wp->w_bufp;
/* if we aren't off the end of the text, move the point to the mouse */
if ((lp=mouseline(wp, ypos)) != NULL && nclicks < 3) {
curwp->w_dotp = lp;
curwp->w_doto = mouseoffset(wp, lp, xpos);
}
/* if we changed windows, update the modelines, abort the new op */
if (wp != lastwp) {
upmode();
return(TRUE);
}
/* perform the region function */
if (nclicks == 1) {
return(copyregion(FALSE, 0));
} else if (nclicks == 2) {
return(yank(FALSE, 1));
} else {
nclicks = 0;
return(TRUE);
}
}
/*
* Move mouse button, up. The up click must be
* in the text region of a window. If the old click was in a
* mode line then the mode line moves to the row of the
* up click. If the old click is not in a mode line then the
* window scrolls. The code in this function is just
* too complex!
*/
PASCAL NEAR movemu(f, n)
int f,n; /* prefix flag and argument */
{
register WINDOW *lastwp;
register WINDOW *wp;
register int lastmodeline; /* was the downclick on a modeline? */
register int deltay;
register int deltax;
#if WINDOW_TEXT
register int redraw_needed; /* is a screen redraw required */
#endif
/* adjust position by screen offset */
ypos -= term.t_roworg;
xpos -= term.t_colorg;
/* no movement... fail the command */
if (lastypos==ypos && lastxpos==xpos)
return(FALSE);
#if !WINDOW_MSWIN
/* if the down click was in the bottom right corner...
then we are resizing */
if (lastypos == term.t_nrow && lastxpos + 1 == term.t_ncol) {
#if WINDOW_TEXT
if (xpos < term.t_ncol || ypos < term.t_nrow)
redraw_needed = TRUE;
else
redraw_needed = FALSE;
#endif
newwidth(TRUE, xpos + 1);
newsize(TRUE, ypos + 1);
#if WINDOW_TEXT
if (redraw_needed) {
refresh_screen(first_screen);
}
#endif
return(TRUE);
}
/* if the down click was in the upper left corner...
then we are moving the screen */
if (lastypos == 0 && lastxpos == 0) {
new_row_org(TRUE, ypos + term.t_roworg);
new_col_org(TRUE, xpos + term.t_colorg);
#if WINDOW_TEXT
refresh_screen(first_screen);
#endif
return(TRUE);
}
#endif
/* if the down click was not in a window.. fail the command
(for example, if we click on the command line) */
if ((lastwp=mousewindow(lastypos)) == NULL)
return(FALSE);
/* did we down click on a modeline? */
lastmodeline = ismodeline(lastwp, lastypos);
/* are we not in a window? fail it then */
if ((wp=mousewindow(ypos)) == NULL)
return(FALSE);
/* how far did we move? */
deltay = lastypos-ypos;
deltax = lastxpos-xpos;
lastypos = ypos;
lastxpos = xpos;
/* if we started on a modeline.... */
if (lastmodeline) {
/* move the window horizontally */
if (deltax != 0 && (diagflag || deltay == 0)) {
lastwp->w_fcol += deltax;
if (lastwp->w_fcol < 0)
lastwp->w_fcol = 0;
lastwp->w_flag |= WFMODE|WFHARD;
if (deltay == 0)
return(TRUE);
}
/* don't allow the bottom modeline to move */
if (lastwp->w_wndp == NULL)
return(FALSE);
/* shrink the current window */
if (deltay > 0) {
if (lastwp != wp)
return(FALSE);
curwp = wp;
curbp = wp->w_bufp;
return(shrinkwind(TRUE, deltay));
}
/* or grow it */
if (deltay < 0) {
if (wp != lastwp->w_wndp)
return(FALSE);
curwp = lastwp;
curbp = lastwp->w_bufp;
return(enlargewind(TRUE, -deltay));
}
}
/* did we up click in a modeline? fail it them */
if (ismodeline(wp, ypos) != FALSE)
return(FALSE);
/* we can not move outside the current window */
if (lastwp != wp)
return(FALSE);
/* move horizontally as well? */
if (deltax != 0 && (diagflag || deltay == 0)) {
wp->w_fcol += deltax;
if (wp->w_fcol < 0)
wp->w_fcol = 0;
wp->w_flag |= WFMODE;
}
/* and move the screen */
return(mvdnwind(TRUE, deltay));
}
/*
* Return a pointer to the WINDOW structure
* for the window in which "row" is located, or NULL
* if "row" isn't in any window. The mode line is
* considered to be part of the window.
*/
WINDOW *PASCAL NEAR mousewindow(row)
register int row;
{
register WINDOW *wp;
/* must be a positiove row! */
if (row < 0)
return(NULL);
/* step through each window on the active screen */
wp = wheadp;
while (wp != NULL) {
/* is this row within the current window? */
if (row < wp->w_ntrows+1)
return(wp);
/* advance to the next window */
row -= wp->w_ntrows+1;
wp = wp->w_wndp;
}
return(NULL);
}
/*
* The row "row" is a row within the window
* whose WINDOW structure is pointed to by the "wp"
* argument. Find the associated line, and return a pointer
* to it. Return NULL if the mouse is on the mode line,
* or if the mouse is pointed off the end of the
* text in the buffer.
*/
LINE *PASCAL NEAR mouseline(wp, row)
register WINDOW *wp;
register int row;
{
register LINE *lp;
row -= wp->w_toprow;
if (row >= wp->w_ntrows + (modeflag ? 0 : 1))
return(NULL);
lp = wp->w_linep;
while (row--) {
if (lp == wp->w_bufp->b_linep) /* Hit the end. */
return(NULL);
lp = lforw(lp);
}
return(lp);
}
/*
* Return the best character offset to use
* to describe column "col", as viewed from the line whose
* LINE structure is pointed to by "lp".
*/
PASCAL NEAR mouseoffset(wp, lp, col)
register WINDOW *wp;
register LINE *lp;
register int col;
{
register int c;
register int offset;
register int curcol;
register int newcol;
offset = 0;
curcol = 0;
col += wp->w_fcol; /* adjust for extended lines */
while (offset != lused(lp)) {
newcol = curcol;
if ((c=lgetc(lp, offset)) == '\t')
newcol += -(newcol % tabsize) + (tabsize - 1);
else if (c<32) /* ISCTRL */
++newcol;
++newcol;
if (newcol > col)
break;
curcol = newcol;
++offset;
}
return(offset);
}
PASCAL NEAR mouse_screen()
{
register SCREEN *screen_ptr; /* screen to test mouse in */
/* if we move the mouse off the windows, check for other windows */
if ((ypos < term.t_roworg) || (xpos < term.t_colorg) ||
(ypos > term.t_roworg + term.t_nrow) ||
(xpos >= term.t_colorg + term.t_ncol)) {
/* scan through the other windows */
screen_ptr = first_screen->s_next_screen;
while (screen_ptr != (SCREEN *)NULL) {
/* is the mouse in this window? */
if ((ypos >= screen_ptr->s_roworg) &&
(xpos >= screen_ptr->s_colorg) &&
(ypos <= screen_ptr->s_roworg + screen_ptr->s_nrow) &&
(xpos <= screen_ptr->s_colorg + screen_ptr->s_ncol)) {
/* select this screen */
select_screen(screen_ptr, FALSE);
lastxpos = -1;
lastypos = -1;
break;
}
/* on to the next screen */
screen_ptr = screen_ptr->s_next_screen;
}
}
}
PASCAL NEAR ismodeline(wp, row)
WINDOW *wp;
int row;
{
/* not on a legal window, say we aren't on a mode line either */
if (wp == (WINDOW *)NULL)
return(FALSE);
/* are we on a modeline? */
if (row == wp->w_toprow+wp->w_ntrows && modeflag)
return(TRUE);
/* no */
return(FALSE);
}
/* The mouse has been used to resize the physical window. Now we need to
let emacs know about the newsize, and have him force a re-draw
*/
PASCAL NEAR resizm(f, n)
int f, n; /* these are ignored... we get the new size info from
the mouse driver */
{
#if WINDOW_TEXT
register int redraw_needed; /* is a screen redraw required */
#endif
/* make sure we are on the proper screen */
mouse_screen();
/* adjust position by screen offset */
ypos -= term.t_roworg;
xpos -= term.t_colorg;
#if WINDOW_TEXT
if (xpos < term.t_ncol || ypos < term.t_nrow)
redraw_needed = TRUE;
else
redraw_needed = FALSE;
#endif
/* change to the new size */
newwidth(TRUE, xpos + 1);
newsize(TRUE, ypos + 1);
#if WINDOW_TEXT
if (redraw_needed) {
refresh_screen(first_screen);
}
#endif
return(TRUE);
}
#else
mousehello()
{
}
#endif